/*
--------------------------------------------------------------------------------
				Ak-Lib. 
			 Project       	: Ak-Lib
			 Group         	: Ak-Lib R&D Team
			 Author        	: Ocean.Wang
			 Create Date 	: 05-01-2010
--------------------------------------------------------------------------------
Code Name 	:  A.K 	~v~
Description	:  Yet Another Cross-Platform Lib.
Cautions    	:
--------------------------------------------------------------------------------
Change History:
Version		: 0.1
Building 		: 05/01/10
10-05.01 first draft, build, debug and test.
--------------------------------------------------------------------------------
*/
#ifndef _EDF_TYPES_H_
#define _EDF_TYPES_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <malloc.h>
	
#ifdef __cplusplus
extern "C" {
#endif


#define _HOST_GNU 		0X0000
#define _HOST_WIN 		0X0001


/* ------------------------------------------------------------------
**	Basic Type
*/
typedef char 				_sInt8;
typedef unsigned char 		_uInt8;
typedef short 				_sInt16;
typedef unsigned short 		_uInt16;
typedef int 				_sInt32;
typedef unsigned int 		_uInt32;
typedef long long 			_sInt64;
typedef unsigned long long 	_uInt64;
typedef double 				_dFloat;

typedef struct{
	char * 		val;
	_sInt32 	len;
}_cSeq;

#define 	EDF_PACK_MIN 	(16)

/* EDF ErrCode */
#define _EDF_E_OOM		0X00001000
#define _EDF_E_UNK		0X00002000
#define _EDF_E_OOR		0X00004000
#define _EDF_E_CRT		0X00008000

#ifndef  	_HOST_OS
#define 	_HOST_OS		_HOST_GNU
#endif

#if 	_HOST_OS == _HOST_WIN
/* In Order to Co-Work with DDK */
#ifndef _WIN32_WINNT
#define _WIN32_WINNT  	0x0600
#endif

#ifndef  WSA_VERSION
#define	 WSA_VERSION  	MAKEWORD(2,0)
#include "winsock2.h"
#endif

#include <windows.h>

#elif 	 _HOST_OS == _HOST_GNU
#include <netinet/in.h>
#include <arpa/inet.h>

#endif

#define _EDF_HTONS(var) 		(var = htons(var))
#define _EDF_NTOHS(var) 		(var = ntohs(var))

#define _EDF_HTONL(var) 		(var = htonl(var))
#define _EDF_NTOHL(var) 		(var = ntohl(var))

typedef union{
	struct{
		_sInt32 	hi;
		_sInt32 	lo;
	};
	_sInt64 	ll;
}_uQuart;

static 	__inline 	_sInt64 	_xhtonll(_sInt64 var)
{
	_uQuart 	quart;
	_sInt32 	hi, lo;

	quart.ll = var;
	if(var != 0){
		hi = _EDF_HTONL(quart.hi);
		lo = _EDF_HTONL(quart.lo);
		quart.hi = lo;
		quart.lo = hi;
	}
	return quart.ll;
}

static 	__inline 	_sInt64 	_xntohll(_sInt64 var)
{
	_uQuart 	quart;
	_sInt32 	hi, lo;

	quart.ll = var;
	if(var != 0){
		hi = _EDF_NTOHL(quart.hi);
		lo = _EDF_NTOHL(quart.lo);
		quart.hi = lo;
		quart.lo = hi;
	}
	return quart.ll;
}

#define _EDF_HTONLL(var) 		(var = _xhtonll(var))
#define _EDF_NTOHLL(var) 		(var = _xntohll(var))


/* ------------------------------------------------------------------
**	Basic Function. User shouldn't Call these Entry Directly.
*/
typedef enum {
	EDF_T_VOID 	= 0,
	EDF_T_S8	= 1,
	EDF_T_U8	= 2,
	EDF_T_S16	= 3,
	EDF_T_U16	= 4,
	EDF_T_S32	= 5,
	EDF_T_U32	= 6,
	EDF_T_S64	= 7,
	EDF_T_U64	= 8,
	EDF_T_DOUBLE= 9,
	EDF_T_STRING= 10,
	EDF_T_UNION = 11,
	EDF_T_STRUCT= 12,
	EDF_T_ENUM	= 13,
	EDF_T_PACK  = 14
}Edf_TypeId ;


/*
**  Format:
**  Fid	: 1 Byte, Bit 0: Array? [(Fid << 1) | ArrayFlag]?
**  Type	: 1 Byte, TypeId
**  iCnt 	: 4 Byte, Item Count
** mCnt	: 4 Byte, Mask Count
** items	: iCnt * sizeof(Type)
** masks	: mCnt * (int (index)+ int(32 mask))
*/
static __inline _sInt32 _xDec_Unknown(_uInt8 * _oPtr, _sInt32 _oLen){
	_uInt8 	_iType, _iFid;
	_sInt32 _iCnt, _mCnt, _sum;
	
	_iFid	= *(_oPtr);
	_iType	= (*(_oPtr + 1) >> 4);
	switch(_iType){
		/* Int8 */
		case EDF_T_S8:
		case EDF_T_U8:
			if(_iFid & 0X01){
				#ifdef __USE_EDF_ENDIAN
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 2)));
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 6)));
				#endif
				_iCnt = *((_sInt32 *)(_oPtr + 2));
				_mCnt = *((_sInt32 *)(_oPtr + 6));
				_sum = 10 + ((_iCnt * sizeof(char)) + (_mCnt * 8));
			}else{
				_sum = 2 + sizeof(char);
			}
			break;
		/* Int16 */
		case EDF_T_S16:
		case EDF_T_U16:
			if(_iFid & 0X01){
				#ifdef __USE_EDF_ENDIAN
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 2)));
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 6)));
				#endif
				_iCnt = *((_sInt32 *)(_oPtr + 2));
				_mCnt = *((_sInt32 *)(_oPtr + 6));
				_sum = 10 + ((_iCnt * sizeof(short)) + (_mCnt * 8));
			}else{
				_sum = 2 + sizeof(short);
			}
			break;
		/* Int32 */
		case EDF_T_S32:
		case EDF_T_U32:
			if(_iFid & 0X01){
				#ifdef __USE_EDF_ENDIAN
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 2)));
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 6)));
				#endif
				_iCnt = *((_sInt32 *)(_oPtr + 2));
				_mCnt = *((_sInt32 *)(_oPtr + 6));
				_sum = 10 + ((_iCnt * sizeof(int)) + (_mCnt * 8));
			}else{
				_sum = 2 + sizeof(int);
			}
			break;
		/* Int64 */
		case EDF_T_S64:
		case EDF_T_U64:
			if(_iFid & 0X01){
				#ifdef __USE_EDF_ENDIAN
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 2)));
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 6)));
				#endif
				_iCnt = *((_sInt32 *)(_oPtr + 2));
				_mCnt = *((_sInt32 *)(_oPtr + 6));
				_sum = 10 + ((_iCnt * sizeof(long long)) + (_mCnt * 8));
			}else{
				_sum = 2 + sizeof(long long);
			}
			break;
		/* Double */
		case EDF_T_DOUBLE:
			if(_iFid & 0X01){
				#ifdef __USE_EDF_ENDIAN
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 2)));
					_EDF_NTOHL(*((_sInt32 *)(_oPtr + 6)));
				#endif
				_iCnt = *((_sInt32 *)(_oPtr + 2));
				_mCnt = *((_sInt32 *)(_oPtr + 6));
				_sum = 10 + ((_iCnt * sizeof(double)) + (_mCnt * 8));
			}else{
				_sum = 2 + sizeof(double);
			}
			break;

		/* cSeq */
		case EDF_T_STRING:
			#ifdef __USE_EDF_ENDIAN
				_EDF_NTOHL(*((_sInt32 *)(_oPtr + 2)));
			#endif
			_sum = *((_sInt32 *)(_oPtr + 2));
			break;
		
		/* Struct / Union */
		case EDF_T_UNION:
		case EDF_T_STRUCT:
		case EDF_T_PACK:
			#ifdef __USE_EDF_ENDIAN
				_EDF_NTOHL(*((_sInt32 *)(_oPtr + 2)));
			#endif
			_sum = *((_sInt32 *)(_oPtr + 2));
			break;

		default:
			return -1;
			break;
	}
	if(_sum > _oLen)
		return -1;
	
	return _sum;
}

#if 0
static __inline void * _xEdfFastCopy(char * dst, char * src, size_t size)
{
	long i;

	i = (long)(size >> 3);
	while(i--){
		*((long long *)dst) = *((long long *)src);
		dst += sizeof(long long);
		src += sizeof(long long);
	}
	i = (long)(size & 0X04);
	if(i){
		*((int *)dst) = *((int *)src);
		dst += sizeof(int);
		src += sizeof(int);
	}
	i = (long)(size & 0X03);
	while(i--){	
		*dst = *src;
		++dst; ++src;
	};
	return (dst - size);
}

#define _xEdfCopy(dst, src, size) \
	do{\
		if(size <= 128){\
			_xEdfFastCopy((char *)(void *)dst, (char *)(void *)src, size);\
		}\
		else{\
			memcpy(dst, src, size);\
		}\
	}while(0)

#else

#define _xEdfCopy 					memcpy
#define _xEdfZero32(_ptr, size) 	memset(_ptr, 0, size * sizeof(int))
#endif


#ifdef __cplusplus
}
#endif

#endif


